/*
 * FileName Projection.h
*/

#ifndef __DEEP_ZOOM_IMAGE_PROJECTION_H__
#define __DEEP_ZOOM_IMAGE_PROJECTION_H__

#include <glib.h>

#define VIEWPORT_SCALE            (65536.0)
#define VIEWPORT_SCALE_RECIPROCAL (1.0 / VIEWPORT_SCALE)

namespace DeepZoomImage
{
	class  Matrix3D
	{
	private:
		double matrix[16];

	protected:
		virtual ~Matrix3D () {}

	public:
		/* @PropertyType=double,DefaultValue=1.0,GenerateAccessors */
		double m_M11;
		/* @PropertyType=double,DefaultValue=0.0,GenerateAccessors */
		double m_M12;
		/* @PropertyType=double,DefaultValue=0.0,GenerateAccessors */
		double m_M13;
		/* @PropertyType=double,DefaultValue=0.0,GenerateAccessors */
		double m_M14;
		/* @PropertyType=double,DefaultValue=0.0,GenerateAccessors */
		double m_M21;
		/* @PropertyType=double,DefaultValue=1.0,GenerateAccessors */
		double m_M22;
		/* @PropertyType=double,DefaultValue=0.0,GenerateAccessors */
		double m_M23;
		/* @PropertyType=double,DefaultValue=0.0,GenerateAccessors */
		double m_M24;
		/* @PropertyType=double,DefaultValue=0.0,GenerateAccessors */
		double m_M31;
		/* @PropertyType=double,DefaultValue=0.0,GenerateAccessors */
		double m_M32;
		/* @PropertyType=double,DefaultValue=1.0,GenerateAccessors */
		double m_M33;
		/* @PropertyType=double,DefaultValue=0.0,GenerateAccessors */
		double m_M34;
		/* @PropertyType=double,DefaultValue=0.0,GenerateAccessors */
		double m_OffsetX;
		/* @PropertyType=double,DefaultValue=0.0,GenerateAccessors */
		double m_OffsetY;
		/* @PropertyType=double,DefaultValue=0.0,GenerateAccessors */
		double m_OffsetZ;
		/* @PropertyType=double,DefaultValue=1.0,GenerateAccessors */
		double m_M44;

		/* @GeneratePInvoke,SkipFactories */
		Matrix3D ();

		/* @SkipFactories */
		Matrix3D (double *m);

		//virtual void OnPropertyChanged (PropertyChangedEventArgs *args, MoonError *error);

		/* @GeneratePInvoke */
		gpointer GetMatrixValues () { return matrix; }

		//
		// Property Accessors
		//
		void SetM11 (double m11)
		{
			m_M11 = m11;
		}
		double GetM11 ()
		{
			return m_M11;
		}

		void SetM12 (double m12)
		{
			m_M12 = m12;
		}
		double GetM12 ()
		{
			return m_M12;
		}

		void SetM13 (double m13)
		{
			m_M13 = m13;
		}
		double GetM13 ()
		{
			return m_M13;
		}

		void SetM14 (double m14)
		{
			m_M14 = m14;
		}
		double GetM14 ()
		{
			return m_M14;
		}

		void SetM21 (double m21)
		{
			m_M21 = m21;
		}
		double GetM21 ()
		{
			return m_M21;
		}

		void SetM22 (double m22)
		{
			m_M22 = m22;
		}
		double GetM22 ()
		{
			return m_M22;
		}

		void SetM23 (double m23)
		{
			m_M23 = m23;
		}
		double GetM23 ()
		{
			return m_M23;
		}

		void SetM24 (double m24)
		{
			m_M24 = m24;
		}
		double GetM24 ()
		{
			return m_M24;
		}

		void SetM31 (double m31)
		{
			m_M31 = m31;
		}
		double GetM31 ()
		{
			return m_M31;
		}

		void SetM32 (double m32)
		{
			m_M32 = m32;
		}
		double GetM32 ()
		{
			return m_M32;
		}

		void SetM33 (double m33)
		{
			m_M33 = m33;
		}
		double GetM33 ()
		{
			return m_M33;
		}

		void SetM34 (double m34)
		{
			m_M34 = m34;
		}
		double GetM34 ()
		{
			return m_M34;
		}

		void SetOffsetX (double offsetX)
		{
			m_OffsetX = offsetX;
		}
		double GetOffsetX ()
		{
			return m_OffsetX;
		}

		void SetOffsetY (double offsetY)
		{
			m_OffsetY = offsetY;
		}
		double GetOffsetY ()
		{
			return m_OffsetY;
		}

		void SetOffsetZ (double offsetZ)
		{
			m_OffsetZ = offsetZ;
		}
		double GetOffsetZ ()
		{
			return m_OffsetZ;
		}

		void SetM44 (double m44)
		{
			m_M44 = m44;
		}
		double GetM44 ()
		{
			return m_M44;
		}

		static void Identity (double *out);
		static void Init (double *out, const double *m);
		static void TransformPoint (double *out, const double *m, const double *in);
		static Rect TransformBounds (const double *m, Rect bounds);
		static void Multiply (double *out, const double *a, const double *b);
		static void Translate (double *out, double tx, double ty, double tz);
		static void Scale (double *out, double sx, double sy, double sz);
		static void RotateX (double *out, double theta);
		static void RotateY (double *out, double theta);
		static void RotateZ (double *out, double theta);
		static void Perspective (double *out, double fieldOfViewY, double aspectRatio, double zNearPlane, double zFarPlane);
		static void Viewport (double *out, double width, double height);
		static bool Inverse (double *out, const double *m);
		static void Affine (double *out, double xx, double xy, double yx, double yy, double x0, double y0);
		static bool IsTranslation (const double *m);
		static bool IsIntegerTranslation (const double *m, int *x0, int *y0);
		static bool Is2DAffine (const double *m);
	};

}

#endif /*__DEEP_ZOOM_IMAGE_PROJECTION_H__*/